<?php

	/**
	 * @package		CoreProject
	 * @subpackage	Mime
	 *
	 * cpr_Mime_Header
	 * cpr_Mime_Headers
	 *
	 */

	class cpr_Mime_Header
	{
		/**
		 * @var	string
		 */
		private $_name;
		
		/**
		 * @var	string
		 */
		private $_value;

		/**
		 * @var	bool
		 */
		private $_isParsed;

		/**
		 * @var	cpr_Mime_GlobalCharset
		 */
		private $_global_charset;
		
		/**
		 * @param	cpr_Mime_GlobalCharset	&$_name
		 * @param	string					$_name
		 * @param	string					$_value = '';
		 * @return	cpr_Mime_Header
		 */
		public function cpr_Mime_Header(&$_gc, $_name, $_value = '', $_isParsed = false)
		{
			$this->_global_charset =& $_gc;
			$this->_name = $_name;
			$this->_value = $_value;
			$this->_isParsed = $_isParsed;
		}

		/**
		 * @return	string
		 */
		public function ToString()
		{
			return $this->_name.': '.$this->GetEncodedValue();
		}

		/**
		 * @return	string
		 */
		public function GetDecodedValue()
		{
			return ($this->_isParsed) ? $this->_value :
				cpr_Mime_Utils::DecodeHeaderString($this->_value,
						$this->_global_charset->GetMailCharset(),
						$this->_global_charset->GetDbCharset(),
						$this->_isEmailAdress());

		}

		/**
		 * @return	string
		 */
		public function GetEncodedValue()
		{
			if ($this->_isParsed)
			{
				if ($this->_isSubject())
				{
					return cpr_Mime_Utils::EncodeHeaderString($this->_value, 
						$this->_global_charset->GetDbCharset(),
						$this->_global_charset->GetOutCharset(), true);
				}
				else if ($this->_isEmailAdress())
				{
					$mailCollection = new cpr_Mime_Emails($this->_global_charset, $this->_value);
					return $mailCollection->ToEncodeString();
				}
				else if ($this->_isWithParameters())
				{
					$parameterCollection = new cpr_Mime_Headers($this->_global_charset, $this->_value);
					return $parameterCollection->ToString(true);
				}
			}

			if (cpr_Core_Utils::IsLatin($this->_value))
			{
				return $this->_value;
			}
			else
			{
				return cpr_Mime_Utils::EncodeHeaderString($this->_value, $this->_global_charset->GetMailCharset(), $this->_global_charset->GetOutCharset());
			}
		}

		/**
		 * @return	string
		 */
		public function Value()
		{
			return $this->_value;
		}

		/**
		 * @return	string
		 */
		public function Name()
		{
			return $this->_name;
		}

		/**
		 * @return bool
		 */
		private function _isEmailAdress()
		{
			$_lowerName = strtolower($this->_name);
			return ($_lowerName == strtolower(CPR_MIME_TO) || $_lowerName == strtolower(CPR_MIME_FROM) ||
					$_lowerName == strtolower(CPR_MIME_CC) || $_lowerName == strtolower(CPR_MIME_BBC) ||
					$_lowerName == strtolower(CPR_MIME_REPLY_TO) || $_lowerName == strtolower(CPR_MIME_RETURN_PATH));
		}

		/**
		 * @return bool
		 */
		private function _isSubject()
		{
			return strtolower($this->_name) == strtolower(CPR_MIME_SUBJECT);
		}

		/**
		 * @return bool
		 */
		private function _isWithParameters()
		{
			return (strtolower($this->_name) == strtolower(CPR_MIME_CONTENT_TYPE) ||
				strtolower($this->_name) == strtolower(CPR_MIME_CONTENT_DISPOSITION));
		}
	}

	class cpr_Mime_Headers extends cpr_Core_Collection
	{
		/**
		 * @var	cpr_Mime_GlobalCharset
		 */
		private $_global_charset;

		/**
		 * @param	cpr_Mime_GlobalCharset	&$_gc
		 * @param	string					$rawData
		 * @return	cpr_Mime_Headers
		 */
		public function cpr_Mime_Headers(&$_gc, $rawData)
		{
			$this->_global_charset =& $_gc;
			$this->Parse($rawData);
			$this->_updateHeadersCharset();
		}
		/**
		 * @param string $rawData
		 */
		public function Parse($rawData)
		{
			$pos1 = (int) strpos($rawData, "\r");
			$pos2 = (int) strpos($rawData, "\n");

			$delimiter = ($pos1 > $pos2) ? "\r" : "\n";
			if ($pos1 > $pos2 && $pos1 + 1 == $pos2)
			{
				$rawData = str_replace("\r", '', $rawData);
				$delimiter = "\n";
			}

			$preheaders = explode($delimiter, $rawData);

			$headers = array();
			foreach ($preheaders as $value)
			{
				if (empty($value))
				{
					continue;
				}

				$value = preg_replace('/\?=[\s]{1,4}=\?/', '?==?', $value);
				$first = substr($value, 0, 1);
				if ($first === ' ' || $first === "\t")
				{
					$index = ((count($headers) - 1) > 0) ? (count($headers) - 1) : 0;
					$headers[$index] .= CPR_CRLF.CPR_TAB.trim($value);
				}
				else
				{
					$headers[] = $value;
				}
			}
			unset($preheaders);

			$this->Clear();
			foreach ($headers as $headerline)
			{
				$header = explode(':', $headerline, 2);
				if (count($header) == 2)
				{
					$this->Add(new cpr_Mime_Header($this->_global_charset, trim($header[0]), trim($header[1])));
				}
			}
		}

		/**
		 * @return string
		 */
		public function ToString($withoutBcc = false)
		{
			$retval = '';
			for ($i = 0, $c = $this->Count(); $i < $c; $i++)
			{
				$header =& $this->Get($i);
				if ($withoutBcc && strtolower($header->Name()) == strtolower(CPR_MIME_BBC))
				{
					continue;
				}
				
				$retval .= $header->ToString().CPR_CRLF;
			}

			return $retval;
		}

		/**
		 * @param	string	$_name
		 * @return	cpr_Mime_Headers|null
		 */
		public function &GetHeaderByName($_name)
		{
			for ($i = 0, $c = $this->Count(); $i < $c; $i++)
			{
				$header =& $this->Get($i);
				if (strtolower($header->Name()) == strtolower($_name))
				{
					return $header;
				}
			}
			$null = null;
			return $null;
		}

		/**
		 * @param	string	$_name
		 * @return	string
		 */
		public function GetHeadersValuesByName($_name)
		{
			$return = array();
			for ($i = 0, $c = $this->Count(); $i < $c; $i++)
			{
				$header =& $this->Get($i);
				if (strtolower($header->Name()) == strtolower($_name))
				{
					$return[] = $header->Value();
				}
			}
			return $return;
		}

		/**
		 * @param	string	$_name
		 * @return	string
		 */
		public function GetHeaderValueByName($_name)
		{
			for ($i = 0, $c = $this->Count(); $i < $c; $i++)
			{
				$header =& $this->Get($i);
				if (strtolower($header->Name()) == strtolower($_name))
				{
					return $header->Value();
				}
			}
			return '';
		}

		/**
		 * @param	string	$_name
		 * @return	string
		 */
		function GetHeaderDecodedValueByName($_name)
		{
			for ($i = 0, $c = $this->Count(); $i < $c; $i++)
			{
				$header =& $this->Get($i);
				if (strtolower($header->Name()) == strtolower($_name))
				{
					return $header->GetDecodedValue();
				}
			}
			
			return '';
		}

		/**
		 * @return	string
		 */
		function GetBoundary()
		{
			$contentTypeHeader =& $this->GetHeaderByName(CPR_MIME_CONTENT_TYPE);
			if ($contentTypeHeader != null)
			{
				$headerParameters = new cpr_Mime_HeaderParameters($this->_global_charset, $contentTypeHeader->Value());
				$param =& $headerParameters->GetByName(CPR_MIME_BOUNDARY_L);
				if (null !== $param)
				{
					return $param->Value();
				}
			}

			return '';
		}

		/**
		 * @return	string
		 */
		public function GetContentID()
		{
			return trim($this->GetHeaderValueByName(CPR_MIME_CONTENT_ID), '<>');
		}

		/**
		 * @return	string
		 */
		public function GetContentLocation()
		{
			return $this->GetHeaderValueByName(CPR_MIME_CONTENT_LOCATION);
		}

		/**
		 * @return	string
		 */
		public function GetContentType()
		{
			return $this->GetHeaderDecodedValueByName(CPR_MIME_CONTENT_TYPE);
		}

		/**
		 * @return	string
		 */
		public function GetDescription()
		{
			return $this->GetHeaderValueByName(CPR_MIME_CONTENT_DESCRIPTION);
		}

		/**
		 * @return	string
		 */
		public function GetDisposition()
		{
			return $this->GetHeaderDecodedValueByName(CPR_MIME_CONTENT_DISPOSITION);
		}

		/**
		 * @return	string
		 */
		public function GetFileName()
		{
			$contentDisposition = $this->GetHeaderDecodedValueByName(CPR_MIME_CONTENT_DISPOSITION);
			if ($contentDisposition)
			{
				$headerParameters = new cpr_Mime_HeaderParameters($this->_global_charset, $contentDisposition);
				$param =& $headerParameters->GetByName(CPR_MIME_FILENAME_L);
				if ($param)
				{
					return $param->Value();
				}
			}
			
			return '';
		}

		/**
		 * @return	string
		 */
		function GetContentTypeName()
		{
			$contentType = $this->GetHeaderDecodedValueByName(CPR_MIME_CONTENT_TYPE);
			if ($contentType)
			{
				$headerParameters = new cpr_Mime_HeaderParameters($this->_global_charset, $contentType);
				$param =& $headerParameters->GetByName(CPR_MIME_NAME_L);
				if ($param)
				{
					return $param->Value();
				}
			}

			return '';
		}

		/**
		 * @return	string
		 */
		function GetContentTypeCharset()
		{
			$contentType = $this->GetHeaderValueByName(CPR_MIME_CONTENT_TYPE);
			if ($contentType)
			{
				$headerParameters = new cpr_Mime_HeaderParameters($this->_global_charset, $contentType);
				$param =& $headerParameters->GetByName(CPR_MIME_CHARSET_L);
				if ($param)
				{
					return $param->Value();
				}
			}

			return '';
		}

		/**
		 * @return	bool
		 */
		public function IsAttachmentMailMessage()
		{
			$contentTypeL = strtolower($this->GetContentType());
			if (false !== strpos($contentTypeL, CPR_MIME_BOUNDARY_L))
			{
				if (false !== strpos($contentTypeL, CPR_MIME_MULTIPART_MIXED_L))
				{
					return true;
				}
				if (false !== strpos($contentTypeL, CPR_MIME_MULTIPART_RELATED_L))
				{
					return true;
				}
				if (false !== strpos($contentTypeL, CPR_MIME_MULTIPART_REPORT_L))
				{
					return true;
				}
			}
			return false;
		}

		/**
		 * @return	bool
		 */
		public function IsAttachmentHeader()
		{
			$contentTypeHeaderParameters = new cpr_Mime_HeaderParameters($this->_global_charset, $this->GetContentType());
			$contentDispositionHeaderParameters = new cpr_Mime_HeaderParameters($this->_global_charset, $this->GetDisposition());
			$contentTypeHeaderValue = $this->GetContentType();
			$contentIDValue = $this->GetContentID();
			$contentDispositionHeaderValue = $this->GetDisposition();

			if (null !== $contentTypeHeaderParameters)
			{
				if (false !== strpos($contentTypeHeaderValue, CPR_MIME_MS_TNEF_L))
				{
					return true;
				}

				$temp =& $contentTypeHeaderParameters->GetByName(CPR_MIME_NAME_L);
				if ($temp && strlen($temp->Value()) > 0)
				{
					return true;
				}
				unset($temp);
			}

			if (null !== $contentDispositionHeaderParameters)
			{
				$temp =& $contentDispositionHeaderParameters->GetByName(CPR_MIME_FILENAME_L);
				if ($temp && strlen($temp->Value()) > 0)
				{
					return true;
				}
				unset($temp);
			}

			if (false !== strpos(strtolower($contentTypeHeaderValue), CPR_MIME_MESSAGE_L)
				|| false !== strpos(strtolower($contentDispositionHeaderValue), CPR_MIME_ATTACHMENT_L)
				|| false !== strpos(strtolower($contentTypeHeaderValue), CPR_MIME_IMAGE_L)
				|| strlen($contentIDValue) > 3)
			{
				return true;
			}

			return false;
		}

		/**
		 * @return bool
		 *
		function IsTextBodyHeader()
		{
			if ($this->Count() == 0)
			{
				return true;
			}

			$contentTypeL = strtolower($this->GetContentType());
			if (!$contentTypeL)
			{
				return false;
			}

			$contentDist = $this->GetDisposition();
			

			$contentTypeHeader =  new cpr_Mime_HeaderParameters($this->_global_charset, $contentTypeL);
			$contentDispositionHeader = ($contentDist) ? new cpr_Mime_HeaderParameters($this->_global_charset, $contentDist) : null;

			$attach = $filename = null;
			if ($contentDispositionHeader)
			{
				$attach = $contentDispositionHeader->GetByName(CPR_MIME_ATTACHMENT_L);
				$filename = $contentDispositionHeader->GetByName(CPR_MIME_FILENAME_L);
			}

			$name = ($contentTypeHeader) ? $contentTypeHeader->GetByName(CPR_MIME_NAME_L) : null;

			if ($attach != null || $filename != null || $name != null)
			{
				return false;
			}

			$filenameValue = ($filename) ? $filename->Value() : '';
			$nameValue = ($name) ? $name->Value() : '';

			if (strlen($filenameValue) > 0 || strlen($nameValue) > 0)
			{
				return false;
			}
			if (false !== strpos($contentTypeL, CPR_MIME_TEXT_HTML) || false !== strpos($contentTypeL, CPR_MIME_TEXT_PLAIN))
			{
				return true;
			}
			return false;
		}*/

		private function _updateHeadersCharset()
		{
			$_charset = $this->GetContentTypeCharset();
			if (strlen($_charset) > 0)
			{
				$this->_global_charset->SetMailCharset($_charset);
			}
		}
	}

